package com.google.code.securityflow.ast

import com.google.code.securityflow.graphviz.{GraphvizTree, GraphvizTreeNode}

abstract sealed class Statement(id: Int, location: SourceLocation) extends Node(id, location) {

  def canonicalName: String;

  def toGraphviz: GraphvizTree = {
    this match {
      case stm@AssignStatement(id, property, expression, _) =>
        GraphvizTreeNode(id, stm.canonicalName, List(property.toGraphviz, expression.toGraphviz));

      case stm@CallStatement(id, expression, _) =>
        GraphvizTreeNode(id, stm.canonicalName, List(expression.toGraphviz));

      case stm@IfStatement(id, condition, body, _) =>
        GraphvizTreeNode(id, stm.canonicalName, List(condition.toGraphviz) ++ body.map(s => s.toGraphviz));

      case stm@WhileStatement(id, condition, body, _) =>
        GraphvizTreeNode(id, stm.canonicalName, List(condition.toGraphviz) ++ body.map(s => s.toGraphviz));
    }
  }

}

case class OutStatement(id: Int, expression: Expression, location: SourceLocation) extends Statement(id, location) {
  override def canonicalName = "OutStatement[L" + location.lineNumber + ":" + location.position + "]";
}

case class AssignStatement(id: Int, property: PropertyAccessExpression, expression: Expression, location: SourceLocation) extends Statement(id, location) {
  override def canonicalName = "AssignStatement[L" + location.lineNumber + ":" + location.position + "]";
}

case class CallStatement(id: Int, expression: Expression, location: SourceLocation) extends Statement(id, location) {
  override def canonicalName = "CallStatement[L" + location.lineNumber + ":" + location.position + "]";
}

case class IfStatement(id: Int, condition: Expression, body: List[Statement], location: SourceLocation) extends Statement(id, location) {
  override def canonicalName = "IfStatement[L" + location.lineNumber + ":" + location.position + "]";
}

case class WhileStatement(id: Int, condition: Expression, body: List[Statement], location: SourceLocation) extends Statement(id, location) {
  override def canonicalName = "WhileStatement[L" + location.lineNumber + ":" + location.position + "]";
}

